#ifndef __THREADPOOL__
#define __THREADPOOL__

#include<iostream>
#include<vector>
#include<queue>
#include<thread>
#include<mutex>
#include<atomic>
#include<future>
#include<functional>
#include<condition_variable>

#include<assert.h>

//#include"../network/eventloop.hpp"
#include"log.hpp"

#define THREADPOOL_MAX_NUM 64
#define THREADPOOL_AUTO_GROW

class Threadpool
{
public:
    typedef std::function<void()> Task;

    Threadpool(unsigned short size = 4)
    {
        assert(size<=THREADPOOL_MAX_NUM);
        add_thread(size);
    }

    //将任务加入队列
    template<typename Fun,typename... Args>
    decltype(auto) post_task(Fun&& f,Args&&... args)
    {
        assert(_threadpool_running);

        //result_of_t函数返回值类型
        using return_type=std::result_of_t<Fun(Args...)>;

        //通过packaged_task创建一个可延迟执行的异步任务,其模板参数为return_type()形式的函数类型
        //通过make_shared创建指向一个函数对象的指针
        //函数对象通过bind绑定func和args，所以函数类型没有参数，为return_type()
        //本质就是shared_ptr task=make_shared<可调用对象（return_type()）>(函数对象（bind）)
        auto task=std::make_shared<std::packaged_task<return_type()>>
            (std::bind(std::forward<Fun>(f),std::forward<Args>(args)...));

        //获得函数返回值
        std::future<return_type> res=task->get_future();

        //将任务以lambda函数执行的形式加入任务队列中  void()
        {
            std::lock_guard<std::mutex> mtx(_threadpool_mutex);
            _threadpool_task_queue.emplace([task](){
                (*task)();
            });
        }

        //若定义自动增长模式，当线程空闲数量不足时，自动添加线程
#ifdef THREADPOOL_AUTO_GROW
        if(_threadpool_thread_num<1&&_threadpool.size()<THREADPOOL_MAX_NUM)
            add_thread(1);
#endif
        //唤醒一个随机线程，线程间相互竞争执行
        _threadpool_cond.notify_one();

        return res;
    }

    //获取空闲线程数量
    int get_idle_thread_num(){return _threadpool_thread_num;}

    //获取线程数量
    int get_thread_num(){return _threadpool.size();}

    ~Threadpool()
    {
        _threadpool_running.store(false);
        _threadpool_cond.notify_all();
        for(auto& thread:_threadpool)
        {
            if(thread.joinable())thread.join();
        }
    }

#ifdef THREADPOOL_AUTO_GROW
private:
#endif
    //添加线程
    void add_thread(unsigned short size)
    {
        for(;_threadpool.size()<THREADPOOL_MAX_NUM&&size>0;--size)
        {
            //向线程池插入线程，通过emplace_back直接构造thread对象，线程执行lambda函数
            _threadpool.emplace_back([this]{
                while(_threadpool_running)
                {
                    Task task;

                    {
                        std::unique_lock<std::mutex> mtx(_threadpool_mutex);
                        //创建线程之后，线程等待，直到线程池停止运行或者任务队列有内容
                        _threadpool_cond.wait(mtx,[this]{
                            return !_threadpool_running||!_threadpool_task_queue.empty();
                        });
                        
                        //若线程被唤醒后，线程池停止运行并且任务队列为空时，线程终止
                        if(!_threadpool_running&&_threadpool_task_queue.empty())return;

                        //获得任务队列队首任务
                        task=move(_threadpool_task_queue.front());
                        _threadpool_task_queue.pop();
                    }

                    //线程开始执行task任务
                    _threadpool_thread_num--;
                    task();
                    _threadpool_thread_num++;
                }
            });
            _threadpool_thread_num++;
        }
    }

private:
    Threadpool(const Threadpool&) = delete;

    Threadpool(Threadpool&&) = delete;

    Threadpool& operator=(const Threadpool&) = delete;

    Threadpool& operator=(Threadpool&&) = delete;

private:
    std::vector<std::thread> _threadpool;       //线程池
    std::queue<Task> _threadpool_task_queue;    //线程池任务队列

    std::atomic<bool> _threadpool_running{true};//线程池运行状态
    std::atomic<int> _threadpool_thread_num{0}; //线程池空闲线程数量

    std::mutex _threadpool_mutex;
    std::condition_variable _threadpool_cond;
};


/*
class Thread
{
private:
    // 用于实现_loop获取的同步关系，避免线程创建了，但是_loop还没有实例化之前去获取_loop
    std::mutex _mutex;             // 互斥锁
    std::condition_variable _cond; // 条件变量
    EventLoop *_loop;              // EventLoop指针变量，这个对象需要在线程内实例化
    std::thread _thread;           // EventLoop对应的线程
private:
    // 实例化 EventLoop 对象，唤醒_cond上有可能阻塞的线程，并且开始运行EventLoop模块的功能
    void ThreadEntry()
    {
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁
            _loop = &loop;
            _cond.notify_all();
        }
        loop.Start();
    }

public:
    // 创建线程，设定线程入口函数
    Thread() : _loop(NULL), _thread(std::thread(&Thread::ThreadEntry, this))
    {
    }

    // 返回当前线程关联的EventLoop对象指针
    EventLoop *GetLoop()
    {
        EventLoop *loop = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁
            _cond.wait(lock, [&]()
                       { return _loop != NULL; }); // loop为NULL就一直阻塞
            loop = _loop;
        }
        return loop;
    }
};

class ThreadPool
{
private:
    int _thread_count;
    int _next_idx;
    EventLoop *_baseloop;
    std::vector<Thread *> _threads;
    std::vector<EventLoop *> _loops;

public:
    ThreadPool(EventLoop *baseloop) : _thread_count(0), _next_idx(0), _baseloop(baseloop)
    {
    }

    void SetThreadCount(int count)
    {
        _thread_count = count;
    }

    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; i++)
            {
                _threads[i] = new Thread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
        return;
    }

    EventLoop *NextLoop()
    {
        if (_thread_count == 0)
        {
            return _baseloop;
        }
        _next_idx = (_next_idx + 1) % _thread_count;
        return _loops[_next_idx];
    }
};
*/

#endif
